package ink.ykb.configurer;

import java.io.PrintWriter;
import java.util.Collections;
import java.util.Map;

import javax.servlet.ServletException;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;

import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.boot.autoconfigure.web.servlet.error.AbstractErrorController;
import org.springframework.boot.web.servlet.error.DefaultErrorAttributes;
import org.springframework.stereotype.Controller;
import org.springframework.web.bind.annotation.RequestMapping;

import ink.ykb.util.CommonResult;
import ink.ykb.util.Constant;
import ink.ykb.util.PlatformRuntimeException;

@Controller
public class ErrorController extends AbstractErrorController {

	/**
	 * log4j 日志
	 */
	private Logger logger = LoggerFactory.getLogger(ErrorController.class);

	public ErrorController() {
		super(new DefaultErrorAttributes());
	}

	@RequestMapping("/error")
	public String getErrorPath(HttpServletRequest request, HttpServletResponse response) {
		// 获取异常
		Exception cause = getCause(request);

		if (isJsonRequest(request, response)) {
			try {
				CommonResult result = CommonResult.resultFail(cause);
				String msg = Constant.objectMapper.writeValueAsString(result);
				response.setHeader("Content-Type", "application/json;charset=utf-8");
				response.setHeader("Content-Encoding", "UTF-8");
				response.setStatus(200);

				PrintWriter out = response.getWriter();

				out.print(msg);
				out.flush();
				out.close();
			} catch (Exception e) {
				e.printStackTrace();
			}
			return null;

		} else {
			Map<String, Object> mode = Collections.unmodifiableMap(getErrorAttributes(request, false));
			Integer status = (Integer) mode.get("status");
			String message = (String) mode.get("message");
			// 友好提示
			String errorMessage = getErrorMessage(cause);

			response.setStatus(status);
			request.setAttribute("errorMessage", errorMessage);
			request.setAttribute("status", status);
			request.setAttribute("cause", cause);

			return "error";
		}
	}

	private boolean isJsonRequest(HttpServletRequest request, HttpServletResponse response) {

		String requestUri = (String) request.getAttribute("javax.servlet.error.request_uri");

		Exception cause = getCause(request);
		if (cause instanceof PlatformRuntimeException) {
			return true;
		}
		if (requestUri != null) {
			if (requestUri.endsWith(".html")) {
				return false;
			}
			if (requestUri.endsWith(".json")) {
				return true;
			}
			if ((request.getHeader("Accept") != null && request.getHeader("Accept").contains("application/json") )
					|| (request.getHeader("Content-Type") != null && ( 
									request.getHeader("Content-Type").contains("application/json") || request.getHeader("Content-Type").contains("application/x-www-form-urlencoded")
							))) {
				return true;
			} else {
				return false;
			}

		}
		return false;
	}

	private String getErrorMessage(Throwable ex) {
		if (ex instanceof PlatformRuntimeException) {
			return ex.getMessage();
		}
		return "服务器错误，请联系管理员";
	}

	private Exception getCause(HttpServletRequest request) {

		Throwable error = (Throwable) request.getAttribute("javax.servlet.error.exception");
		if (error != null) {
			while (error instanceof ServletException && error.getCause() != null) {
				error = ((ServletException) error).getCause();
			}
		}

		return (Exception)error;
	}

	@Override
	public String getErrorPath() {
		return null;
	}

}
